#include "global.h"
#include "service/include/port/swei_log.h"
#include "misc/misc_server.h"
#include "service/include/swei_common.h"
#include "service/include/port/swei_wrapper.h"
// #include <17 wireless/mdm_socket.h>
#include "public/errno.h"
#include "misc/rtc_app.h"



#include "modem/qlmodem/task_modem.h"
#include "task/mmgr/include/mmgr_file.h"
#include "misc/misc_api.h"
#include "flash_main.h"
#include "task/comm/co_heartbeat.h"
#include "stdlib.h"

static uint32_t iot_working_id = 0;

/***********************************************************************
 * 函数名称: swei_gen_workid
 * 作    者:   harvey.huang
 * 设计日期: 2024-11-18 11:02
 * 功能描述: 供其他模块调用,生成tbox的工作id
 * 参    数:
 * 返 回 值:
 * 修改日期:          修改人          修改内容
 ***********************************************************************/
void swei_gen_workid(void)
{
    static bool prev_dev_power_off = true;

    bool is_dev_pwroff =  is_ebike_mcu_off();
    

    /* IOT刚上电或者判断到仪表开机动作，生成一个新的WORK ID */
    if( (0 == iot_working_id) \
        || ( (false == is_dev_pwroff) && (prev_dev_power_off != is_dev_pwroff)) ) {

        srand(swei_get_device_timestamp());
        
        iot_working_id = rand();

        log_i("IOT generates a new workid[%u].", iot_working_id);
        
    }

    prev_dev_power_off = is_dev_pwroff;

}



void _imei_str_to_bcd(uint8_t imei_buf[], uint8_t bcd_buf[]);
/***********************************************************************
 * 函数名称: swei_get_workid
 * 作    者:   yanfeng
 * 设计日期: 2023-08-08 11:02
 * 功能描述: 供其他模块调用,获取tbox的工作id
 * 参    数:
 * 返 回 值:
 * 修改日期:          修改人          修改内容
 ***********************************************************************/
uint32_t swei_get_workid(void)
{
    return iot_working_id; // TBOX_WORKING_ID;
}

/********************************* DEVICE API WRAPPER ****************************/

#include "bsp.h"
/// @brief 获取开机秒数
/// @param  
/// @return 
uint32_t swei_getsec(void)
{
    return getsec();
}

uint32_t swei_getms(void)
{
    return getms();
}

#include "mmgr/include/mmgr_misc.h"
#include "mmgr/include/mmgr_pdp.h"
/// @brief 获取设备网络状态
/// @param
/// @return
int32_t swei_network_is_ready(void)
{
    int32_t net_status = 0, rat_state = 0;

    /** 获取注册装填 */
    modem_get_netreg_status(&net_status, &rat_state);
    if (NETREG_NO == net_status && NET_INVAL == rat_state)
        return false;

    /** 获取激活状态 */
    if (!mmgr_pdp_status_get())
        return false;

    return true;
}

/// @brief 网络重连接口
/// @param  
void swei_network_reconnect(void)
{
    int32_t res = qltask_modem_reboot();
    log_w("modem reboot, res :%d!\r\n", res);
}

#include "service/include/swei_cert.h"

// /// @brief 获取设备上电状态和激活状态
// /// @param power_state 
// /// @param active_state 
// void swei_system_state_get(int8_t *power_state, int8_t *active_state)
// {
//     if(power_state)
//     {
//         // *power_state = tbox_get_power_state();
//     }

//     if(active_state)
//     {
//         // *active_state = tbox_get_active_state();
//     }
// }

/// @brief 判断定时器是否超时timeout秒
/// @param start_time 
/// @param timeout 
/// @return 
bool  swei_timeout_sec(uint32_t start_time, uint32_t timeout)
{
    return timeout_sec(start_time, timeout);
}


/// @brief 判断定时器是否超时timeout ms
/// @param start_time 
/// @param timeout 
/// @return 
bool swei_timeout_ms(uint32_t start_time, uint32_t timeout)
{
    return timeout_ms(start_time, timeout);
}

/**
 * @brief 返回设备时间戳
 * @return uint32_t 
 */
uint32_t swei_get_device_timestamp(void)
{
    //return time(NULL);
    return get_timestamp();
}


/********************************* DEVICE API END ****************************/

/********************************* SOCKET API WRAPPER ****************************/
#include "misc/misc_dev.h"

/// @brief socket 建立后处理
/// @param
void swei_socket_enstablish_hook(void)
{
    // 测试模式下不连接服务器
}

/// @brief socket 关闭前预处理
/// @param
void swei_socket_distablish_hook(void)
{
    // qltask_mqtt_broker_unregister(PROT_MQTT_BROKER_ID);
    // vTaskDelay(MS2TICKS(2000));
}



/// @brief socket 连接的地址信息获取
/// @param iphost
/// @param max_iphost_len
/// @param port
/// @param is_ssl
void swei_socket_host_get(char *iphost, uint16_t max_iphost_len, uint16_t *port, uint8_t *is_ssl)
{
    server_params_t server;

    misc_server_param_get(&server);

    if(is_ssl)
        *is_ssl = server.is_ssl;
    if(iphost)
        snprintf(iphost, max_iphost_len, "%s", server.ipaddr);
    if(port)
        *port = server.port;
}


/// @brief ssl 证书获取
/// @param ssl_data_ptr
void swei_socket_cert_get(ssl_cert_t *ssl_data_ptr)
{
    if(ssl_data_ptr)
    {
        ssl_data_ptr->is_ca_need = 1;

        const char *cer_file_ptr = misc_ssl_cacert_get();
        if(strlen(cer_file_ptr) > 0)
            ssl_data_ptr->ca_ptr = cer_file_ptr;
        else
            ssl_data_ptr->ca_ptr = tls_ca_cert;
        
        ssl_data_ptr->is_cert_need = 0;
        ssl_data_ptr->cert_ptr = NULL;
        ssl_data_ptr->key_ptr = NULL;
    }
}


#include "modem/qlmodem/task_modem.h"

extern ssl_cfg_t ssl_cfg;
/// @brief 打开一个socket
/// @param type 
/// @param ip 
/// @param port 
/// @param local 
/// @param mode 
/// @return 0 - socket开启成功
int32_t swei_socket_open(int32_t type, const char *ip, unsigned short port, unsigned short local, int32_t mode)
{
    int32_t socket_id = -EIO;

    if (type == SWEI_SSL)
    {
        socket_id = qltask_modem_socket_open(SOCKET_SSL, &ssl_cfg, ip, port, local, mode);
    }
    else
    {
        socket_id = qltask_modem_socket_open(SOCKET_TCP, NULL, ip, port, local, mode);
    }       

    if (socket_id >= 0) {
        log_w("socket[%d] open!\r\n", socket_id);
    } else {
//        log_e("socket open failed, res: %d\r\n", socket_id);
        qltask_modem_manual_socket_nfm_clear();
    }

    return socket_id;
}

/// @brief 
/// @param socket_id 
/// @return 
int32_t swei_socket_close(int32_t socket_id)
{
    int32_t res = qltask_modem_socket_close(socket_id);
    
    log_w("socket[%d] close, res: %d!\r\n", socket_id, res);

    return res;
}

/// @brief 套节字写入函数
/// @param socket_id 
/// @param buf 
/// @param cnt 
/// @return 
ssize_t swei_socket_write(int32_t socket_id, const void *buf, size_t cnt)
{
#ifndef NDEBUG
    char show_buf[512] = {0};
    for(uint16_t i = 0; i < cnt; i++)
    {
        snprintf(&show_buf[2 * i], sizeof(show_buf) - 2 * i, "%02x ", ((char *)buf)[i]);
        if (2 * i >= sizeof(show_buf) - 2)
            break;
    }
    log_i("socket[%d] send [len:%d]: %s.\r\n", socket_id, cnt, show_buf);
#endif

    return qltask_modem_socket_write(socket_id, buf, cnt);
}

#include "utils/utils_timer.h"
/**
 * @brief
 * @param  socket_id        My Param doc
 * @param  buf              My Param doc
 * @param  cnt              My Param doc
 * @param  timeout          My Param doc
 * @return ssize_t
 */
ssize_t swei_socket_write_timeout(int32_t socket_id, const void *buf, size_t cnt, uint32_t timeout)
{
    utils_time_t tm = {0};
    ssize_t ret     = 0;
    int32_t res     = -EBUSY;

#ifndef NDEBUG
    char show_buf[512] = {0};
    for (uint16_t i = 0; i < cnt; i++) {
        snprintf(&show_buf[2*i], 256 - 2*i, "%02x ", ((char *)buf)[i]);
        if (2*i >= sizeof(show_buf) - 2) {
            break;
        }
    }
    log_d("socket[%d] send[len: %d]: %s, timeout:%d\r\n", socket_id, cnt, show_buf, timeout);
#endif

    utils_time_countdown_ms(&tm, timeout);
    if ((ret = qltask_modem_socket_write(socket_id, buf, cnt)) > 0) { // > 0 -> != 0
        /**
         * 等待发送超时;
         */
        while (!utils_time_is_expired(&tm)) {
            if (-EBUSY == (res = qltask_modem_socket_write_query(socket_id))) {
                osDelay(10);
                continue;
            }

            if (0 == res) {
                log_i("socket[%d] send successful!\r\n", socket_id);
                break;
            } else {
                log_e("socket[%d] send failed, res = %d!\r\n", socket_id, res);
                return res;
            }
        }
    }

    if (-EBUSY == res) {
       log_e("socket[%d] send busy, res = %d!\r\n", socket_id, res);
       return res;
    }

    log_i("socket[%d] write %d bytes, result:%d\r\n", socket_id, cnt, ret);

    return ret;
}

/// @brief 
/// @param socket_id 
/// @return 
int32_t swei_socket_write_query(int32_t socket_id)
{
    return qltask_modem_socket_write_query(socket_id);
}

/// @brief 
/// @param socket_id 
/// @param buf 
/// @param cnt 
/// @return 
ssize_t swei_socket_read(int32_t socket_id, void *buf, size_t cnt)
{
    return qltask_modem_socket_read(socket_id, buf, cnt);
}


#include "mmgr/include/mmgr_file.h"
int32_t swei_file_upload(const char *name, uint8_t *buf, uint32_t len)
{
    int32_t ret = mmgr_file_data_upload((void *)name, buf, len, 60);

    if (0 != ret)
    {
        log_e("mmgr file <%s> store failed! ret=%d\r\n", name, ret);
    }
    else
    {
        log_d("mmgr file <%s> store...  size=%d\r\n", name, len);
    }

    return ret;
}
/********************************* SOCKET API END ****************************/

/********************************* DEVICE API WRAPPER ****************************/
#include "misc/misc_api.h"
/**
 * @description: 设备恢复出厂
 * @return {*}
 * @Date: 2023-11-11 10:43:51
 * @modification:
 */
int32_t swei_system_restore(uint32_t delay_reboot_ms)
{
    tbox_system_restore(delay_reboot_ms);

    return 0;
}

/**
 * @description: 设备重启
 * @return {*}
 * @Date: 2023-11-11 10:43:51
 * @modification:
 */
int32_t swei_system_reboot(uint32_t delay_reboot_ms)
{
    tbox_system_reboot(delay_reboot_ms);

    return 0;
}
/********************************* TOOL API END ****************************/
